﻿namespace System.Workflow.ComponentModel.Compiler
{
    using Microsoft.CSharp;
    using Microsoft.VisualBasic;
    using Microsoft.Win32;
    using System;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Security;

    internal static class CompilerHelpers
    {
        private const string CompilerVersionKeyword = "CompilerVersion";
        private static CodeDomProvider csharpProvider = null;
        private const string NDPSetupRegistryBranch = @"SOFTWARE\Microsoft\NET Framework Setup\NDP";
        private static bool? useDotNet20 = null;
        private static CodeDomProvider vbProvider = null;
        private static string versionNumber = null;
        private const string VersionNumber20 = "v2.0";
        private const string VersionNumber35 = "v3.5";

        internal static CodeDomProvider CreateCodeProviderInstance(Type type)
        {
            if (!useDotNet20.HasValue)
            {
                useDotNet20 = new bool?(type.GetConstructor(new Type[] { typeof(IDictionary<string, string>) }) == null);
            }
            if (useDotNet20 == true)
            {
                if (type == typeof(CSharpCodeProvider))
                {
                    return new CSharpCodeProvider();
                }
                if (type == typeof(VBCodeProvider))
                {
                    return new VBCodeProvider();
                }
                return (CodeDomProvider) Activator.CreateInstance(type);
            }
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add("CompilerVersion", VersionNumber);
            return (CodeDomProvider) Activator.CreateInstance(type, new object[] { dictionary });
        }

        internal static CodeDomProvider GetCodeDomProvider(SupportedLanguages language)
        {
            if (language == SupportedLanguages.CSharp)
            {
                return CSharpProvider;
            }
            return VBProvider;
        }

        internal static SupportedLanguages GetSupportedLanguage(IServiceProvider serviceProvider)
        {
            SupportedLanguages cSharp = SupportedLanguages.CSharp;
            IWorkflowCompilerOptionsService service = serviceProvider.GetService(typeof(IWorkflowCompilerOptionsService)) as IWorkflowCompilerOptionsService;
            if (service != null)
            {
                cSharp = GetSupportedLanguage(service.Language);
            }
            return cSharp;
        }

        internal static SupportedLanguages GetSupportedLanguage(string language)
        {
            SupportedLanguages cSharp = SupportedLanguages.CSharp;
            if (string.IsNullOrEmpty(language) || ((string.Compare(language, "VB", StringComparison.OrdinalIgnoreCase) != 0) && (string.Compare(language, "VisualBasic", StringComparison.OrdinalIgnoreCase) != 0)))
            {
                return cSharp;
            }
            return SupportedLanguages.VB;
        }

        internal static SupportedLanguages GetSupportedLanguage(IWorkflowCompilerOptionsService workflowCompilerOptions)
        {
            SupportedLanguages cSharp = SupportedLanguages.CSharp;
            if (workflowCompilerOptions != null)
            {
                cSharp = GetSupportedLanguage(workflowCompilerOptions.Language);
            }
            return cSharp;
        }

        private static bool IsNetFx35Installed()
        {
            try
            {
                RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP");
                if (key == null)
                {
                    return false;
                }
                string[] subKeyNames = key.GetSubKeyNames();
                if (subKeyNames == null)
                {
                    return false;
                }
                foreach (string str in subKeyNames)
                {
                    if (str.StartsWith("v3.5", StringComparison.OrdinalIgnoreCase))
                    {
                        return true;
                    }
                }
            }
            catch (Win32Exception)
            {
            }
            catch (SecurityException)
            {
            }
            catch (UnauthorizedAccessException)
            {
            }
            catch (IOException)
            {
            }
            return false;
        }

        private static CodeDomProvider CSharpProvider
        {
            get
            {
                if (csharpProvider == null)
                {
                    csharpProvider = CreateCodeProviderInstance(typeof(CSharpCodeProvider));
                }
                return csharpProvider;
            }
        }

        private static CodeDomProvider VBProvider
        {
            get
            {
                if (vbProvider == null)
                {
                    vbProvider = CreateCodeProviderInstance(typeof(VBCodeProvider));
                }
                return vbProvider;
            }
        }

        private static string VersionNumber
        {
            get
            {
                if (versionNumber == null)
                {
                    if (IsNetFx35Installed())
                    {
                        versionNumber = "v3.5";
                    }
                    else
                    {
                        versionNumber = "v2.0";
                    }
                }
                return versionNumber;
            }
        }
    }
}

